```html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>数据流中实时计算中位数技术解析</title>
    <link rel="stylesheet" href="https://cdn.staticfile.org/font-awesome/6.4.0/css/all.min.css">
    <link rel="stylesheet" href="https://cdn.staticfile.org/tailwindcss/2.2.19/tailwind.min.css">
    <link href="https://fonts.googleapis.com/css2?family=Noto+Serif+SC:wght@400;500;600;700&family=Noto+Sans+SC:wght@300;400;500;700&display=swap" rel="stylesheet">
    <script src="https://cdn.jsdelivr.net/npm/mermaid@latest/dist/mermaid.min.js"></script>
    <style>
        body {
            font-family: 'Noto Sans SC', Tahoma, Arial, Roboto, "Droid Sans", "Helvetica Neue", "Droid Sans Fallback", "Heiti SC", "Hiragino Sans GB", Simsun, sans-serif;
            background-color: #f8fafc;
            color: #1e293b;
            line-height: 1.6;
        }
        h1, h2, h3, h4 {
            font-family: 'Noto Serif SC', serif;
            font-weight: 600;
            color: #1e293b;
        }
        .drop-cap::first-letter {
            float: left;
            font-size: 4.5rem;
            line-height: 0.65;
            margin: 0.1em 0.2em 0 0;
            color: #4f46e5;
            font-weight: bold;
        }
        .code-block {
            background-color: #1e293b;
            border-radius: 0.5rem;
            overflow: hidden;
        }
        .code-header {
            background-color: #334155;
            color: #e2e8f0;
            padding: 0.75rem 1rem;
            display: flex;
            justify-content: space-between;
            align-items: center;
        }
        .btn-copy {
            background-color: #4f46e5;
            color: white;
            border: none;
            padding: 0.25rem 0.75rem;
            border-radius: 0.25rem;
            cursor: pointer;
            transition: all 0.2s;
        }
        .btn-copy:hover {
            background-color: #4338ca;
        }
        pre {
            margin: 0;
            padding: 1.5rem;
            color: #e2e8f0;
            overflow-x: auto;
        }
        .card {
            transition: transform 0.3s ease, box-shadow 0.3s ease;
        }
        .card:hover {
            transform: translateY(-5px);
            box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04);
        }
        .pros-cons-item {
            padding: 1rem;
            border-radius: 0.5rem;
            margin-bottom: 1rem;
        }
        .highlight {
            position: relative;
        }
        .highlight::after {
            content: '';
            position: absolute;
            bottom: 0;
            left: 0;
            width: 100%;
            height: 30%;
            background-color: rgba(79, 70, 229, 0.2);
            z-index: -1;
            transform: scaleX(1.05);
        }
        .footer-link {
            transition: color 0.3s ease;
        }
        .footer-link:hover {
            color: #a5b4fc;
        }
    </style>
</head>
<body class="antialiased">
    <!-- Hero Section -->
    <section class="relative bg-gradient-to-r from-indigo-900 to-indigo-700 text-white py-24 px-4 sm:px-6 lg:px-8">
        <div class="max-w-4xl mx-auto text-center">
            <h1 class="text-4xl md:text-5xl font-bold mb-6">实时数据流中位数计算</h1>
            <p class="text-xl md:text-2xl text-indigo-100 mb-8">双堆结构的优雅解决方案</p>
            <div class="bg-white/10 backdrop-blur-sm p-6 rounded-xl inline-block">
                <i class="fas fa-lightbulb text-yellow-300 text-3xl mb-2"></i>
                <p class="text-indigo-50 italic">"在处理无界数据流时，双堆结构提供了时间复杂度最优的优雅解决方案"</p>
            </div>
        </div>
    </section>

    <!-- Main Content -->
    <div class="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8 py-12">
        <!-- Introduction -->
        <section class="mb-16">
            <p class="drop-cap text-lg leading-relaxed">在数据流中实时计算中位数是一个挑战，因为数据流是动态的、无界的，且不断更新。为了高效地处理这个问题，我们需要一个能支持高效插入、删除和快速中位数查询的数据结构。一个常见的方法是使用两个堆（最大堆和最小堆）来实现这一目标。</p>
        </section>

        <!-- Algorithm Overview -->
        <section class="mb-16">
            <h2 class="text-3xl font-bold mb-6 text-indigo-800 border-b-2 border-indigo-200 pb-2">数据流中实时计算中位数的方案</h2>
            
            <div class="grid md:grid-cols-2 gap-8 mb-10">
                <div class="card bg-white p-6 rounded-xl shadow-md">
                    <div class="flex items-center mb-4">
                        <div class="bg-indigo-100 text-indigo-800 p-3 rounded-full mr-4">
                            <i class="fas fa-layer-group text-xl"></i>
                        </div>
                        <h3 class="text-xl font-bold">基本思路</h3>
                    </div>
                    <p class="text-gray-700 mb-4">使用两个优先队列（堆）来维护数据流中的元素：</p>
                    <ul class="space-y-2">
                        <li class="flex items-start">
                            <i class="fas fa-caret-right text-indigo-500 mt-1 mr-2"></i>
                            <span><strong class="text-indigo-600">最大堆（max-heap）</strong>：存储数据流中较小的一半元素</span>
                        </li>
                        <li class="flex items-start">
                            <i class="fas fa-caret-right text-indigo-500 mt-1 mr-2"></i>
                            <span><strong class="text-indigo-600">最小堆（min-heap）</strong>：存储数据流中较大的一半元素</span>
                        </li>
                    </ul>
                    <p class="text-gray-700 mt-4">最大堆用来保证堆顶是数据流中较小部分的最大值，最小堆用来保证堆顶是数据流中较大部分的最小值。</p>
                </div>

                <!-- Mermaid Diagram -->
                <div class="card bg-white p-6 rounded-xl shadow-md flex items-center justify-center">
                    <div class="mermaid">
                        graph TD
                            A[新元素] --> B{比较}
                            B -->|≤ maxHeap.top| C[maxHeap]
                            B -->|> maxHeap.top| D[minHeap]
                            C --> E[平衡堆大小]
                            D --> E
                            E --> F{中位数查询}
                            F -->|堆大小相等| G[(maxHeap.top + minHeap.top)/2]
                            F -->|maxHeap大1| H[maxHeap.top]
                    </div>
                </div>
            </div>

            <div class="bg-blue-50 border-l-4 border-blue-500 p-6 rounded-r-lg mb-8">
                <div class="flex">
                    <div class="flex-shrink-0">
                        <i class="fas fa-info-circle text-blue-500 text-xl"></i>
                    </div>
                    <div class="ml-3">
                        <h3 class="text-lg font-medium text-blue-800">关键点</h3>
                        <div class="mt-2 text-blue-700">
                            <p>算法核心在于维护两个堆的平衡，确保它们的元素数量差异不超过1。这种平衡使得中位数查询可以在常数时间内完成。</p>
                        </div>
                    </div>
                </div>
            </div>
        </section>

        <!-- Implementation Details -->
        <section class="mb-16">
            <h2 class="text-3xl font-bold mb-6 text-indigo-800 border-b-2 border-indigo-200 pb-2">详细实现</h2>
            
            <h3 class="text-2xl font-semibold mb-4 text-gray-800">Java代码示例</h3>
            <div class="code-block mb-8">
                <div class="code-header">
                    <div class="flex items-center">
                        <div class="w-3 h-3 rounded-full bg-red-500 mr-2"></div>
                        <div class="w-3 h-3 rounded-full bg-yellow-500 mr-2"></div>
                        <div class="w-3 h-3 rounded-full bg-green-500"></div>
                    </div>
                    <button class="btn-copy">
                        <i class="fas fa-copy mr-1"></i>复制代码
                    </button>
                </div>
                <pre><code class="language-java">import java.util.PriorityQueue;

public class MedianFinder {
    // 最大堆（小顶堆，取负值以模拟最大堆）
    private PriorityQueue&lt;Integer&gt; maxHeap;
    // 最小堆
    private PriorityQueue&lt;Integer&gt; minHeap;

    /** 初始化数据结构 */
    public MedianFinder() {
        // 小顶堆，取负值实现最大堆
        maxHeap = new PriorityQueue&lt;&gt;((a, b) -&gt; b - a);
        // 大顶堆
        minHeap = new PriorityQueue&lt;&gt;();
    }

    /** 添加一个数到数据流中 */
    public void addNum(int num) {
        // 先将元素放入最大堆
        maxHeap.offer(num);

        // 将最大堆的最大元素移到最小堆中
        minHeap.offer(maxHeap.poll());

        // 如果最小堆的元素数量多于最大堆，则将最小堆的最小元素移到最大堆中
        if (minHeap.size() &gt; maxHeap.size()) {
            maxHeap.offer(minHeap.poll());
        }
    }

    /** 获取中位数 */
    public double findMedian() {
        if (maxHeap.size() &gt; minHeap.size()) {
            return maxHeap.peek();
        } else {
            return (maxHeap.peek() + minHeap.peek()) / 2.0;
        }
    }

    public static void main(String[] args) {
        MedianFinder mf = new MedianFinder();
        mf.addNum(1);
        System.out.println(mf.findMedian()); // 输出1.0
        mf.addNum(2);
        System.out.println(mf.findMedian()); // 输出1.5
        mf.addNum(3);
        System.out.println(mf.findMedian()); // 输出2.0
    }
}</code></pre>
            </div>

            <div class="grid md:grid-cols-2 gap-8 mt-10">
                <div>
                    <h3 class="text-2xl font-semibold mb-4 text-gray-800">数据结构选择</h3>
                    <div class="bg-white p-6 rounded-xl shadow-sm">
                        <ul class="space-y-4">
                            <li>
                                <div class="flex items-start">
                                    <div class="flex-shrink-0 h-10 w-10 rounded-full bg-indigo-100 flex items-center justify-center mr-4">
                                        <i class="fas fa-database text-indigo-600"></i>
                                    </div>
                                    <div>
                                        <h4 class="font-medium text-gray-900">最大堆（maxHeap）</h4>
                                        <p class="text-gray-600">存储数据流中较小的一半元素。由于 Java 的 PriorityQueue 是小顶堆，因此需要将元素取负值来模拟最大堆的行为。</p>
                                    </div>
                                </div>
                            </li>
                            <li>
                                <div class="flex items-start">
                                    <div class="flex-shrink-0 h-10 w-10 rounded-full bg-purple-100 flex items-center justify-center mr-4">
                                        <i class="fas fa-database text-purple-600"></i>
                                    </div>
                                    <div>
                                        <h4 class="font-medium text-gray-900">最小堆（minHeap）</h4>
                                        <p class="text-gray-600">存储数据流中较大的一半元素。Java 的 PriorityQueue 默认是小顶堆，所以可以直接使用。</p>
                                    </div>
                                </div>
                            </li>
                        </ul>
                    </div>
                </div>
                <div>
                    <h3 class="text-2xl font-semibold mb-4 text-gray-800">维护堆的大小</h3>
                    <div class="bg-white p-6 rounded-xl shadow-sm">
                        <ul class="space-y-3">
                            <li class="flex items-start">
                                <span class="flex-shrink-0 h-6 w-6 rounded-full bg-green-100 text-green-800 flex items-center justify-center mr-3">1</span>
                                <span>在每次插入新元素后，检查两个堆的大小，并根据需要调整它们的平衡</span>
                            </li>
                            <li class="flex items-start">
                                <span class="flex-shrink-0 h-6 w-6 rounded-full bg-green-100 text-green-800 flex items-center justify-center mr-3">2</span>
                                <span>确保最大堆的大小总是比最小堆大1个元素或相等</span>
                            </li>
                            <li class="flex items-start">
                                <span class="flex-shrink-0 h-6 w-6 rounded-full bg-green-100 text-green-800 flex items-center justify-center mr-3">3</span>
                                <span>算法的时间复杂度为 O(log n) 插入，O(1) 查询</span>
                            </li>
                        </ul>
                    </div>
                </div>
            </div>
        </section>

        <!-- Pros and Cons -->
        <section class="mb-16">
            <h2 class="text-3xl font-bold mb-6 text-indigo-800 border-b-2 border-indigo-200 pb-2">优缺点分析</h2>
            
            <div class="grid md:grid-cols-2 gap-6">
                <div class="pros-cons-item bg-green-50 border border-green-200">
                    <div class="flex items-center mb-2">
                        <i class="fas fa-check-circle text-green-600 mr-2 text-xl"></i>
                        <h3 class="text-xl font-semibold text-green-800">优点</h3>
                    </div>
                    <ul class="space-y-2 text-green-700">
                        <li class="flex items-start">
                            <i class="fas fa-angle-right mt-1 mr-2"></i>
                            <span>时间复杂度优异：插入操作为 O(log n)，查询中位数为 O(1)</span>
                        </li>
                        <li class="flex items-start">
                            <i class="fas fa-angle-right mt-1 mr-2"></i>
                            <span>不需要对整个数据流进行排序，节省了时间和空间</span>
                        </li>
                        <li class="flex items-start">
                            <i class="fas fa-angle-right mt-1 mr-2"></i>
                            <span>适用于动态变化的数据流场景</span>
                        </li>
                    </ul>
                </div>
                
                <div class="pros-cons-item bg-red-50 border border-red-200">
                    <div class="flex items-center mb-2">
                        <i class="fas fa-exclamation-circle text-red-600 mr-2 text-xl"></i>
                        <h3 class="text-xl font-semibold text-red-800">缺点</h3>
                    </div>
                    <ul class="space-y-2 text-red-700">
                        <li class="flex items-start">
                            <i class="fas fa-angle-right mt-1 mr-2"></i>
                            <span>实现相对复杂，需要管理两个优先队列</span>
                        </li>
                        <li class="flex items-start">
                            <i class="fas fa-angle-right mt-1 mr-2"></i>
                            <span>需要确保两个堆的大小平衡</span>
                        </li>
                        <li class="flex items-start">
                            <i class="fas fa-angle-right mt-1 mr-2"></i>
                            <span>空间复杂度为 O(n)，需要存储所有元素</span>
                        </li>
                    </ul>
                </div>
            </div>
        </section>

        <!-- Performance Analysis -->
        <section class="mb-16">
            <h2 class="text-3xl font-bold mb-6 text-indigo-800 border-b-2 border-indigo-200 pb-2">性能分析</h2>
            
            <div class="bg-white rounded-xl shadow-md overflow-hidden">
                <div class="p-6">
                    <div class="mermaid">
                        xychart-beta
                            title "双堆法时间复杂度分析"
                            x-axis "操作" ["插入", "查询"]
                            y-axis "时间复杂度" 0 --> 5
                            bar [3, 1]
                            bar [2.5, 1.5]
                            set-option annotations ["O(log n)", "O(1)"]
                    </div>
                </div>
                <div class="bg-gray-50 px-6 py-4">
                    <p class="text-gray-600">上图展示了双堆法在不同操作下的时间复杂度表现。可以看到查询操作的时间复杂度为常数时间 O(1)，而插入操作的时间复杂度为对数时间 O(log n)。</p>
                </div>
            </div>
        </section>
    </div>

    <!-- Footer -->
    <footer class="bg-gray-900 text-gray-300 py-12">
        <div class="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8">
            <div class="flex flex-col items-center">
                <div class="flex items-center mb-6">
                    <i class="fas fa-laptop-code text-indigo-400 text-2xl mr-3"></i>
                    <span class="text-xl font-semibold text-white">技术小馆</span>
                </div>
                <div class="mb-6">
                    <a href="http://www.yuque.com/jtostring" class="footer-link text-indigo-300 hover:underline">http://www.yuque.com/jtostring</a>
                </div>
                <div class="flex space-x-6">
                    <a href="#" class="footer-link hover:text-white">
                        <i class="fab fa-github text-xl"></i>
                    </a>
                    <a href="#" class="footer-link hover:text-white">
                        <i class="fab fa-twitter text-xl"></i>
                    </a>
                    <a href="#" class="footer-link hover:text-white">
                        <i class="fab fa-linkedin text-xl"></i>
                    </a>
                </div>
            </div>
        </div>
    </footer>

    <script>
        // Initialize Mermaid
        mermaid.initialize({
            startOnLoad: true,
            theme: 'default',
            fontFamily: 'Noto Sans SC, sans-serif'
        });

        // Copy button functionality
        document.querySelectorAll('.btn-copy').forEach(button => {
            button.addEventListener('click', () => {
                const codeBlock = button.closest('.code-block').querySelector('code');
                const text = codeBlock.textContent;
                
                navigator.clipboard.writeText(text).then(() => {
                    button.innerHTML = '<i class="fas fa-check mr-1"></i>已复制';
                    setTimeout(() => {
                        button.innerHTML = '<i class="fas fa-copy mr-1"></i>复制代码';
                    }, 2000);
                });
            });
        });

        // Add hover effect to code blocks
        document.querySelectorAll('.code-block').forEach(block => {
            block.addEventListener('mouseenter', () => {
                block.querySelector('.btn-copy').style.opacity = '1';
            });
            block.addEventListener('mouseleave', () => {
                block.querySelector('.btn-copy').style.opacity = '0.8';
            });
        });
    </script>
</body>
</html>
```